package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"xagent/internal/distributed"

	"github.com/asynkron/protoactor-go/actor"
)

func main() {
	// Parse command line flags
	port := flag.Int("port", 8090, "Port to listen on")
	flag.Parse()

	// Use port in cluster configuration
	config := &distributed.Config{
		Port: *port,
	}

	// Create actor system
	system := actor.NewActorSystem()

	// Create cluster manager with config
	clusterManager, err := distributed.NewClusterManager(system, config)
	if err != nil {
		fmt.Printf("Failed to create cluster manager: %v\n", err)
		os.Exit(1)
	}

	// Create decision manager
	decisionManager := distributed.NewDecisionManager(system, clusterManager)

	// Create learning manager
	learningManager := distributed.NewLearningManager(system, clusterManager)

	// Create prediction manager
	predictionManager := distributed.NewPredictionManager(system, clusterManager)

	// Create adaptation manager
	adaptationManager := distributed.NewAdaptationManager(system, clusterManager)

	// Create context with cancellation
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Start cluster manager
	if err := clusterManager.Start(ctx); err != nil {
		fmt.Printf("Failed to start cluster manager: %v\n", err)
		os.Exit(1)
	}

	// Example: Initiate a decision
	decision, err := decisionManager.InitiateDecision(ctx, "resource_allocation", []string{"option1", "option2"})
	if err != nil {
		fmt.Printf("Failed to initiate decision: %v\n", err)
	} else {
		fmt.Printf("Decision initiated: %s\n", decision.Id)
	}

	// Example: Start distributed learning
	learning, err := learningManager.StartTraining(ctx, "model1", []string{"initial_data"})
	if err != nil {
		fmt.Printf("Failed to start training: %v\n", err)
	} else {
		fmt.Printf("Training started: %s\n", learning.Id)
	}

	// Example: Request prediction
	features := map[string]float64{"cpu_usage": 0.75}
	convertedFeatures := make(map[string]float32)
	for k, v := range features {
		convertedFeatures[k] = float32(v)
	}
	prediction, err := predictionManager.RequestPrediction(ctx, "model1", convertedFeatures)
	if err != nil {
		fmt.Printf("Failed to request prediction: %v\n", err)
	} else {
		fmt.Printf("Prediction requested: %s\n", prediction.Id)
	}

	// Example: Initiate adaptation
	currentState := map[string]float64{"response_time": 100.0}
	stateStr := fmt.Sprintf("%v", currentState)
	adaptation, err := adaptationManager.InitiateAdaptation(ctx, "model1", stateStr)
	if err != nil {
		fmt.Printf("Failed to initiate adaptation: %v\n", err)
	} else {
		fmt.Printf("Adaptation initiated: %s\n", adaptation.Id)
	}

	// Wait for interrupt signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	<-sigChan

	// Stop cluster manager
	if err := clusterManager.Stop(); err != nil {
		fmt.Printf("Failed to stop cluster manager: %v\n", err)
	}
}

func printStatus(msg string, err error) {
	if err != nil {
		fmt.Printf("%s: Failed - %v\n", msg, err)
	} else {
		fmt.Printf("%s: Success\n", msg)
	}
}
